#!/usr/bin/env python
# -*- coding: utf-8 -*-

from __future__ import absolute_import
# http://docs.python.org/whatsnew/pep-328.html

from cherrypy import request, response
from webpyte import dir_wp, flash, redirect, url, ShowUserThisException
from webpyte.gensher import gensher, page, fragment
from webpyte.auth.controller import auth, require
from webpyte.formetto import Formetto
from webpyte.upload import Upload, Download
from webpyte.ajax import as_json
from webpyte.text import to_filename, find_new_title
from os.path import join
from unipath import Path


class ImageMan(object):
    '''A pluggable and somewhat adaptable image manager.'''
    def __init__(self, app, dir, url, id):
        '''
        *app* is a Webpyte application, used to find templates and add routes.
        
        *dir* is the physical directory to be managed. (With uploaded images.)
        
        *url* is the virtual directory to be managed.
        
        *id* is a unique identifier for this ImageMan (because multiple
        packages might integrate it, each with its own settings). It should
        contain only common letters and numbers. The id is used when creating
        the routes. For instance, if id='MyImageMan', then you can write:
        
            u = url_for("MyImageMan", action="show")
        '''
        self.app = app
        self.dir = Path(dir)
        self.url = url
        self.id = id
        config = app.config.get(self.id, {})
        self.size_limit = config.get('size_limit', '730x730')
        # All templates for this package are in this directory
        app.gensher.add_search_path(dir_wp + "/imageman/templates")
        self._add_routes(app.dispatch.connect, id)
    
    def _add_routes(self, connect, id):
        connect(name=id, route=id+"/:action", action="show",
                controller=self,
                requirements = dict(action="show_upload|upload|show|" \
                    "get_names|delete|rename|reduce|alt|insert"))
    
    @require(auth.has_permission("PostEdit"))
    @page("imageman_upload.html")
    def show_upload(self, size_limit=None, uploaded=None):
        """Presents the ImageMan upload interface (in an iframe)."""
        return dict(
            pagetitle = 'Upload to ' + self.url,
            f = Formetto(),
            action = url(self.id, action='upload'),
            size_limit = size_limit or self.size_limit,
            uploaded=uploaded,
        )
    
    @require(auth.has_permission("PostEdit"))
    def upload(self, upload=None, url=None, size_limit=None, name=None):
        # File name cannot always be inferred from the URL.
        # Plone, for instance, has URLs that end in "/image"
        if url and not name:
            return gensher.error \
                (u'Ao usar URL é preciso digitar o nome do arquivo.')
        try:
            up = Download(url) if url else Upload(upload)
        except ShowUserThisException, e:
            return gensher.error(e)
        size_limit = size_limit or self.size_limit # a string.
        size = size_limit.lower().split('x')       # a tuple.
        try:
            up.resize_image_if_larger_than(size)
        except IOError, e:
            return gensher.error('{0} - Is "{1}" really an image file?' \
                .format(str(e), up.filename))
        name = to_filename(name or upload.filename, for_web=True)
        up.path = name
        up.dir = self.dir
        if not up.ext:  up.ext = '.jpg' # by default.
        # Change stem to avoid replacing an existing file
        up.path = find_new_title(up.dir, up.stem + up.ext)
        up.write_file()
        flash(up.status)
        return self.show_upload(size_limit=size_limit, uploaded=up.stem+up.ext)
    
    @require(auth.has_permission("PostEdit"))
    @page("imageman_show.html")
    def show(self):
        """Presents the ImageMan interface."""
        return dict(
            pagetitle = 'Image Manager: ' + self.url,
            img_container = self.url,
            upload_url    = url(self.id, action='show_upload'),
            get_names_url = url(self.id, action='get_names'),
            rename_url    = url(self.id, action='rename'),
            delete_url    = url(self.id, action='delete'),
        )
    
    @require(auth.has_permission('PostEdit'))
    @as_json()
    def get_names(self):
        '''Dumps the image names as json.'''
        files = [f.name for f in self.dir.listdir(filter=lambda x: x.isfile())]
        return dict(images=files)
    
    @require(auth.has_permission('PostEdit'))
    @as_json()
    def rename(self, oldname, newname):
        '''Renames a specified image.'''
        # Fix the name the user typed
        newname = to_filename(newname, for_web=True)
        # Rename and return the name
        img = Path(self.dir, oldname)
        new = Path(self.dir, newname)
        if not new.ext:  new += img.ext # ensure file extension
        img.rename(new)
        return dict(image=new.name)
    
    @require(auth.has_permission("PostRemove"))
    @as_json()
    def delete(self, image):
        """Removes an image."""
        img = Path(self.dir, image)
        img.remove()
        return dict(image=image)



if __name__ == "__main__":
    pass
